﻿using System;
using System.Collections.Generic;
using Ur;
using Sargon;

using Sargon.Rendering;

namespace Pixels
{
    static public class Render
    {

        static internal Rendering.Camera Camera;

        static Render() {

        }

        static public Canvas canvas;

        static public Sprite sprite(Texture t, crds2 position, float scale, bool temporary) {
            var spr = new Sprite();
            spr.texture = t;
            spr.centered = true;
            spr.coords = position;
            spr.scale = new crds2(scale, scale);
            spr.temporary = temporary;
            if (canvas != null) canvas.add(spr);
            return spr;

        }

        static public Sprite spriteInBox(Texture t, Rect rect, bool temporary) {
            var spr = new Sprite();
            spr.texture = t;
            spr.fit(rect);
            spr.temporary = temporary;
            if (canvas != null) canvas.add(spr);
            return spr;
        }


        static public Sprite[] tile(Texture t, crds2 ul, crds2 lr, float scale = 1f) {
            var d = (lr - ul);

            var lst = new List<Sprite>();

            float w1 = t.width * scale;
            float h1 = t.height * scale;

            var nx = Maths.floor(d.x / w1 - float.Epsilon) + 1;
            var ny = Maths.floor(d.y / h1 - float.Epsilon) + 1;

            for (var y = 0; y < ny; y++)
                for (var x = 0; x < nx; x++) {
                    var spr = new Sprite();
                    spr.texture = t;

                    float w2 = w1, h2 = h1; // w2 and h2 are truncated complexes
                    if (x == nx - 1) w2 = d.x - (nx - 1) * w1;
                    if (y == ny - 1) h2 = d.y - (ny - 1) * h1;
                    spr.fit(w1 * x, h1 * y, w2, h2);
                    spr.explicit_subrect(0, 0, Maths.floor(t.width * w2 / w1), Maths.floor(t.height * h2 / h1));

                    lst.Add(spr);
                }

            foreach (var spr in lst) canvas.add(spr);
            return lst.ToArray();
        }


        static public Sprite[] ninegrid(Texture t, crds2 ul, crds2 lr, bool temporary) {

            var s = new Sprite[9];
            for (int i = 0; i < 9; i++) {
                s[i] = new Sprite();
                s[i].texture = t;
            }

            var m = int.Parse(t.get_metadata("margin"));
            var w = (lr.x - ul.x);
            var h = (lr.y - ul.y);
            var mw = w - 2 * m;
            var mh = h - 2 * m;

            var tmw = t.width - 2 * m;
            var tmh = t.height - 2 * m;

            var x0 = ul.x;
            var x1 = ul.x + m;
            var x2 = lr.x - m;
            var x3 = lr.x;

            var y0 = ul.y;
            var y1 = ul.y + m;
            var y2 = lr.y - m;
            var y3 = lr.y;

            s[0].fit(x0, y0, m, m); s[0].named_area("upper_left");
            s[1].fit(x1, y0, mw, m); s[1].named_area("upper");
            s[2].fit(x2, y0, m, m); s[2].named_area("upper_right");

            s[3].fit(x0, y1, m, mh); s[3].named_area("left");
            s[4].fit(x1, y1, mw, mh); s[4].named_area("center");
            s[5].fit(x2, y1, m, mh); s[5].named_area("right");

            s[6].fit(x0, y2, m, m); s[6].named_area("lower_left");
            s[7].fit(x1, y2, mw, m); s[7].named_area("lower");
            s[8].fit(x2, y2, m, m); s[8].named_area("lower_right");

            //var lst = new List<Sprite>();
            //lst.AddRange(s);
            //foreach (var spr in lst) canvas.add(spr);
            //return lst.ToArray();

            foreach (var ss in s) { ss.temporary = temporary; canvas.add(ss); }
            return s;
        }

        static public Text text(string txt, crds2 position, float width = 1000f, float scale = 1f, bool temporary = false) {

            var to = new Text(txt);
            to.rect = new Rect(position.x, position.y, width, 100);
            to.scale = new crds2(scale, scale);
            to.temporary = temporary;
            if (canvas != null) canvas.add(to);
            return to;
        }

        internal static Text textInBox(string text, Rect rect, bool temporary) {

            var to = new Text(text, rect);
            to.rect = rect; // = rect.lo.lerp(rect.hi, 0.5f);
            to.scale = crds2.one;
            to.temporary = temporary;
            if (canvas != null) canvas.add(to);
            return to;

        }

        private const float LINE_WIDTH = 0.5f;

        static public Sprite line2d(Texture t, crds2 A, crds2 B, float width, bool temporary) {
            var spr = new Sprite();
            spr.texture = t;
            var a = A;
            var b = B;
            var z = 1f;
            var d = b - a;
            var w = width * Camera.zoom * z * LINE_WIDTH;
            if (w < 1f) w = 1f;
            spr.fit(a.x, a.y, d.lenght, w);
            spr.centered = true;
            spr.coords = a.lerp(b, 0.5f);
            spr.rotation = Ur.Maths.get_angle(d.x, d.y);
            spr.temporary = temporary;
            if (canvas != null)
                canvas.add(spr);

            return spr;
        }

        static public Sprite line3d(Texture t, crds3 A, crds3 B, float width, bool temporary) {

            var spr = new Sprite();
            spr.texture = t;
            var a = Camera.project(A);
            var b = Camera.project(B);
            //var z = (a.z + b.z) * 0.5f;
            var z = 0;
            var d = b - a;
            var w = width * Camera.zoom * z * LINE_WIDTH;
            if (w < 1f) w = 1f;
            spr.fit(a.x, a.y, d.lenght, w);
            spr.centered = true;
            spr.coords = a.lerp(b, 0.5f);
            spr.rotation = Ur.Maths.get_angle(d.x, d.y);
            spr.temporary = temporary;
            spr.zed = z;
            if (canvas != null)
                canvas.add(spr);

            return spr;

        }

        
    }
}
